﻿/*
ImageGlass Project - Image viewer for Windows
Copyright (C) 2012 DUONG DIEU PHAP
Project homepage: http://imageglass.codeplex.com

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using ImageGlass.Core;
using ImageGlass.Feature;
using System.IO;
using Microsoft.Win32;
using System.Threading;

namespace ImageGlass
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();            
        }

        #region Local variable

        ImgMan man = new ImgMan();                      // Mảng lưu trữ danh sách file ảnh
        int cur = 0;                                    // Index của hình ảnh đang xem
        string path = null;                             // Đường dẫn thư mục hình ảnh đang xem
        string initFile = null;                         // Ten file hình ảnh đang xem
        Rectangle rect = Rectangle.Empty;               // Widnow size memory (kiosk mode)
        Rectangle[] zoom = new Rectangle[10];           // The zoom level memory
        bool isZoom = false;                            // đặt dấu hiệu cho biết zoom để loại bỏ trường hợp load ảnh 2 lần ở Paint()
        bool smoothPan = true;                          // Smooth panning?
        bool lockEdges = true;                          // When moving, lock onto screen edges?
        int scrollIdent = 0;                            // Sticky keys scrolling filter
        bool slideshow = false;                         // Bắt đầu slide show
        Point chrome = Point.Empty;                     // Windowborder offset
        bool recursive = false;                         // Tìm kiếm đệ quy trong thư mục
        List<string> dsExt = new List<string>();        // danh sach cac dinh dang file ho tro
        bool isShowThumbnail = false;                   // co hien thumbnail ko?
        bool imgError = false;                          // Kiểm tra xem ảnh hiện tại có bị lỗi không?
        List<string> dsImage = new List<string>();

        #endregion


        #region Drag - drop
        private void frmMain_DragOver(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.All;
        }

        private void frmMain_DragDrop(object sender, DragEventArgs e)
        {
            try
            {
                Prepare(((string[])e.Data.GetData(DataFormats.FileDrop))[0]);
            }
            catch { }
        }
        #endregion


        #region Preparing image
        /// <summary>
        /// Open an image
        /// </summary>
        private void OpenFile()
        {
            OpenFileDialog o = new OpenFileDialog();

            if (o.ShowDialog() == DialogResult.OK && File.Exists(o.FileName))
            {
                Prepare(o.FileName);
            }
            o.Dispose();
        }

        /// <summary>
        /// Lấy tất cả các file ảnh trong thư mục
        /// </summary>
        /// <param name="path"></param>
 
        private void Prepare(string path)
        {            
            if (File.Exists(path) == false && Directory.Exists(path) == false)
                return;

            isZoom = false;
            cur = 0;//dat lai index cua hinh anh

            if (File.Exists(path))
            {
                initFile = path;
                path = path.Substring(0, path.LastIndexOf("\\") + 1);//lay duong dan thu muc                
            }
            else if (Directory.Exists(path))
            {
                path = path.Replace("\\\\", "\\");                
            }

            this.path = path;//gan lam thu muc hinh anh
            dsImage = new List<string>(); //danh sach ten tap tin hinh anh
            GetFiles(dsImage, path, -1);//loc lay danh sach hinh anh co trong thu muc
            man.Dispose();
            man = new ImgMan(path, dsImage.ToArray());//gan ds hinh anh

            //tim index cua hinh anh
            cur = dsImage.IndexOf(Path.GetFileName(initFile));
            if (cur == -1)//ảnh không thể hiển thị
            {
                imgError = true;
                picMain.Size = man.ErrorImage().Size;
                picMain.Image = man.ErrorImage();
                this.Text = "ImageGlass - " + initFile;
                lblStatus.Text = ImageGlass_ImageInfo.GetFileSize(initFile);

                return;
            }

            NextPic(0);

            //show thumbnail image--------------------------------------------------------------------------
            if (isShowThumbnail)
            {
                LoadThumnailImage(dsImage.ToArray());
            }
            

        }

        /// <summary>
        /// Clear and reload all thumbnail image
        /// </summary>
        /// <param name="dsImage"></param>
        private void LoadThumnailImage(string[] dsImage)
        {
            ThumbBar.ClickEventHander eventClickItem = new ThumbBar.ClickEventHander(toolThumbBarItem_click);
            toolThumbBar.RemoveAll();
            toolThumbBar.AddItems(dsImage, path, eventClickItem);
            toolThumbBar.SetSelectedIndex(cur);
            toolThumbBar.LoadThumbnailItems();
        }

        /// <summary>
        /// Sự kiện thumbnail item click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolThumbBarItem_click(object sender, EventArgs e)
        {
            ThumbBar.ThumbItem ti = (ThumbBar.ThumbItem)sender;            
            UnselectedAllThumbnailItems();

            ti.IsSelected = true;
            cur = toolThumbBar.SelectedIndex;
            NextPic(0);
        }

        /// <summary>
        /// unselected all items
        /// </summary>
        private void UnselectedAllThumbnailItems()
        {
            for (int i = 0; i < toolThumbBar.Items.Count; i++)
            {
                toolThumbBar.Items[i].IsSelected = false;                
            }

        }

        /// <summary>
        /// Lọc ra các tập tin định dạng hình ảnh từ thư mục
        /// </summary>
        /// <param name="dsFile"></param>
        /// <param name="path"></param>
        /// <param name="len"></param>
        void GetFiles(List<string> dsFile, string path, int len)
        {
            int a = dsFile.Count;
            if (len < 0)
            {
                len = path.Length;
            }

            dsFile.AddRange(System.IO.Directory.GetFiles(path));

            for (; a < dsFile.Count; a++)
            {
                dsFile[a] = dsFile[a].Substring(len);
                string ext = dsFile[a].Substring(dsFile[a].LastIndexOf(".") + 1).ToLower();

                // loc lai danh sach cac file co ext ho tro
                if (dsExt.IndexOf(ext) == -1)
                {
                    dsFile.RemoveAt(a);
                    a--;
                }
            }

            //neu tim kiem de quy
            if (recursive)
            {
                string[] sub = System.IO.Directory.GetDirectories(path);
                foreach (string e in sub)
                {
                    GetFiles(dsFile, e, len);
                }
            }
        }

        /// <summary>
        /// Change to the dir'th picture from this one
        /// </summary>
        /// <param name="dir">Steps, signed</param>
        void NextPic(int dir)
        {
            if (man.Length < 1)
            {
                this.Text = "ImageGlass";
                lblStatus.Text = string.Empty;
                return;
            }

            isZoom = false;
            cur += dir;
            if (man.Length == 0) return;
            if (cur >= man.Length) cur = 0;
            if (cur < 0) cur = man.Length - 1;


            picMain.Image = null;
            string statusStr = string.Empty;
            statusStr = (cur + 1) + "/" + man.Length + " file(s)    ";
            this.Text = "ImageGlass - " + man.GetPath(cur);
            Application.DoEvents();
            Image im = null;

            try
            {
                im = man.Get(cur);
                imgError = man.imgError;

                if (im.Width <= sp0.Panel1.Width && im.Height <= sp0.Panel1.Height)
                {
                    Point p = new Point();
                    p.X = sp0.Panel1.Width / 2 - im.Width / 2;
                    p.Y = sp0.Panel1.Height / 2 - im.Height / 2;

                    picMain.Image = im;
                    picMain.Bounds = new Rectangle(p, picMain.Image.Size);
                }
                else
                {
                    Recenter(im);
                    picMain.Image = im;
                }

                statusStr += picMain.Image.Width + " x " + picMain.Image.Height + " px    " +
                               ImageGlass_ImageInfo.GetFileSize(man.GetPath(cur));


                //giai phong bo nho
                if (cur - 1 > -1 && cur < man.Length)
                {
                    man.Unload(cur - 1);
                }
            }
            catch//(Exception ex)
            {
                picMain.Image = null;
                Application.DoEvents();
                //MessageBox.Show(ex.Source + " -> " + ex.Message + "\n" + ex.StackTrace);
                if (!File.Exists(man.GetPath(cur)))
                {
                    man.Unload(cur);
                }
            }

            //booster
            string hkey = "HKEY_CURRENT_USER\\SOFTWARE\\PhapSoftware\\ImageGlass\\";
            int v = 0;
            int.TryParse(Registry.GetValue(hkey, "BoostValue", 0).ToString(), out v);
            man.loadNext = v;

            lblStatus.Text = statusStr;

            //select thumbnail
            toolThumbBar.SelectedIndex = cur;

            System.GC.Collect();
        }
        #endregion


        #region Key event
        private void frmMain_KeyDown(object sender, KeyEventArgs e)
        {
            //this.Text = e.KeyValue.ToString();

            //===================================\\'
            //=  Thực hiện load file bằng cách  =\\'
            //=    dán dữ liệu từ Clipboard     =\\'
            //===================================\\'
            if (e.KeyCode == Keys.V && e.Control && !e.Shift && !e.Alt)//Ctrl + V
            {
               //Kiem tra co file trong clipboard khong?-------------------------------------------------------------------------
                if (Clipboard.ContainsFileDropList())
                {
                    string[] sFile = (string[])Clipboard.GetData(System.Windows.Forms.DataFormats.FileDrop);
                    int fileCount = 0;

                    fileCount = sFile.Length;
                   
                    //neu co file thi load
                    Prepare(sFile[0]);
                }


                //Kiem tra co image trong clipboard khong?------------------------------------------------------------------------
                //CheckImageInClipboard: ;
                else if (Clipboard.ContainsImage())
                {
                    picMain.Image = Clipboard.GetImage();
                }
               

                //Kiem tra co duong dan (string) trong clipboard khong?-----------------------------------------------------------
                //CheckPathInClipboard: ;
                else if (Clipboard.ContainsText())
                {
                    if (File.Exists(Clipboard.GetText()) || Directory.Exists(Clipboard.GetText()))
                    {
                        Prepare(Clipboard.GetText());
                    }
                }


            }           
 


            // Rotation Counterclockwise----------------------------------------------------
            if (e.KeyValue == 188 && e.Control && !e.Shift && !e.Alt)//Ctrl + ,
            {
                btnRotateLeft_Click(null, null);
                return;
            }
            //Rotate Clockwise--------------------------------------------------------------
            if (e.KeyValue == 190 && e.Control && !e.Shift && !e.Alt)//Ctrl + .
            {
                btnRotateRight_Click(null, null);
                return;
            }
           
            //Play slideshow----------------------------------------------------------------
            if (e.KeyValue == 122 && !e.Control && !e.Shift && !e.Alt)//F11
            {
                btnSlideShow_Click(null, null);
                return;
            }

            //Exit slideshow----------------------------------------------------------------
            if (e.KeyValue == 27 && !e.Control && !e.Shift && !e.Alt)//ESC
            {
                if (slideshow)
                {
                    mnuExitSlideshow_Click(null, null);
                }
                return;
            }

            //Start / stop slideshow---------------------------------------------------------
            if (slideshow && e.KeyCode == Keys.Space && !e.Control && !e.Shift && !e.Alt)//SPACE
            {
                if (timSlideShow.Enabled)//stop
                {
                    mnuStopSlideshow_Click(null, null);
                }
                else//start
                {
                    mnuStartSlideshow_Click(null, null);
                }
                
                return;
            }

            // Help ------------------------------------------------------------------------
            if (e.KeyValue == 112 && !e.Control && !e.Shift && !e.Alt)//F1
            {
                btnHelp_Click(null, null);
                return;
            }

            //Previous Image----------------------------------------------------------------
            if ((e.KeyValue == 33 || e.KeyValue == 37) && 
                e.Control == false && e.Shift == false && e.Alt == false)//Left arrow / PageUp
            {
                NextPic(-1);
                return;
            }

            //Next Image---------------------------------------------------------------------
            if ((e.KeyValue == 34 || e.KeyValue == 39) && 
                e.Control == false && e.Shift == false && e.Alt == false)//Right arrow / Pagedown
            {
                NextPic(1);
                return;
            }

            //Zoom + ------------------------------------------------------------------------
            if (e.KeyValue == 187 && e.Control && !e.Shift && !e.Alt)// Ctrl + =
            {
                btnZoomIn_Click(null, null);
                return;
            }

            //Zoom - ------------------------------------------------------------------------
            if (e.KeyValue == 189 && e.Control && !e.Shift && !e.Alt)// Ctrl + -
            {
                btnZoomOut_Click(null, null);
                return;
            }

            //Scale to Width------------------------------------------------------------------
            if (e.KeyCode == Keys.W && e.Control && !e.Shift && !e.Alt)// Ctrl + W
            {
                btnScaletoWidth_Click(null, null);
                return;
            }

            //Scale to Height------------------------------------------------------------------
            if (e.KeyCode == Keys.H && e.Control && !e.Shift && !e.Alt)// Ctrl + W
            {
                btnScaletoHeight_Click(null, null);
                return;
            }

            //Auto size window------------------------------------------------------------------
            if (e.KeyCode == Keys.M && e.Control && !e.Shift && !e.Alt)// Ctrl + W
            {
                btnWindowAutosize_Click(null, null);
                return;
            }

            //Auto size image ----------------------------------------------------------------
            if (e.KeyValue == 48 && e.Control && !e.Shift && !e.Alt)// Ctrl + 0
            {
                btnScale11_Click(null, null);
                return;
            }

            //Full screen--------------------------------------------------------------------
            if (e.Alt && e.KeyCode == Keys.Enter && !e.Control && !e.Shift)//Alt + Enter
            {
                btnFullScreen.PerformClick();
                return;
            }

            //Open file----------------------------------------------------------------------
            if (e.KeyValue == 79 && e.Control && !e.Shift && !e.Alt)// Ctrl + O
            {
                OpenFile();
                return;
            }

            //Convert file----------------------------------------------------------------------
            if (e.KeyValue == 83 && e.Control && !e.Shift && !e.Alt)// Ctrl + S
            {
                btnConvert_Click(null, null);
                return;
            }

            //Refresh Image------------------------------------------------------------------
            if (e.KeyValue == 116)//F5
            {
                btnRefresh_Click(null, null);
                return;
            }

            //Goto image---------------------------------------------------------------------
            if (e.KeyValue == 71 && e.Control && !e.Shift && !e.Alt)//Ctrl + G
            {
                try
                {
                    int n = Convert.ToInt32(InputBox.Derp("Goto image ...", (cur + 1).ToString())) - 1;
                    cur = n;
                    NextPic(0);
                }
                catch { }
                return;
            }

            //Extract frames-----------------------------------------------------------------
            if (e.KeyCode == Keys.E && e.Control && !e.Shift && !e.Alt)//Ctrl + E
            {
                try
                {
                    man.Get(cur).GetFrameCount(System.Drawing.Imaging.FrameDimension.Time);
                    mnuExtractFrames_Click(null, null);
                }
                catch { }
                return;
            }

            //Detele to Recycle bin----------------------------------------------------------
            if (e.KeyCode == Keys.Delete && !e.Control && !e.Shift && !e.Alt)//Delete
            {
                mnuRecycleBin_Click(null, null);
                return;
            }

            //Detele From Hark disk----------------------------------------------------------
            if (e.KeyCode == Keys.Delete && !e.Control && e.Shift && !e.Alt)//Shift + Delete
            {
                mnuDelete_Click(null, null);
                return;
            }

            //Open image location------------------------------------------------------------
            if (e.KeyCode == Keys.L && e.Control && !e.Shift && !e.Alt)//Ctrl + L
            {
                mnuImageLocation_Click(null, null);
                return;
            }

            //Image properties----------------------------------------------------------------
            if (e.KeyCode == Keys.I && e.Control && !e.Shift && !e.Alt)//Ctrl + I
            {
                mnuProperties_Click(null, null);
                return;
            }

            //Show thumbnail-------------------------------------------------------------------
            if (e.KeyCode == Keys.T && e.Control && !e.Shift && !e.Alt)// Ctrl + T
            {
                btnThumb.PerformClick();
                return;
            }

            //Caro background------------------------------------------------------------------
            if (e.KeyCode == Keys.B && e.Control && !e.Shift && !e.Alt)// Ctrl + B
            {
                btnCaro.PerformClick();
                return;
            }

            //ImageGlass Settings---------------------------------------------------------------
            if (e.KeyCode == Keys.P && e.Control && !e.Shift && !e.Alt)// Ctrl + P
            {
                btnSetting_Click(null, null);
                return;
            }

            //Rename image-----------------------------------------------------------------------
            if (e.KeyValue == 113)//F2
            {
                string ofn, fn;
                ofn = fn = man.GetName(cur);
                string ext = fn.Substring(fn.LastIndexOf("."));
                fn = fn.Substring(0, fn.Length - ext.Length);
                string str = InputBox.Derp("Enter new filename", fn);
                if (str == null) return;
                fn = str + ext;
                if (ofn == fn) return;
                man.Unload(cur);
                picMain.Image = null;
                lblStatus.Text = "Moving...";
                Application.DoEvents();
                System.IO.File.Move(path + ofn, path + fn);
                man.SetName(cur, fn);
                //nextPic(e.Alt ? 1 : 0);
                int n = cur; //buffer
                NextPic(1); //continue
                man.Get(n); //reload
                return;
            }
           
            // Sap hinh anh voi duong bien duoi-----------------------------------------------------
            if (e.KeyCode == Keys.Down)
            {
                //Sap bien duoi
                if (e.Control && !e.Shift && !e.Alt)//Ctrl + Down
                {
                    scrollSmooth(picMain.Left, picMain.Top + sp0.Panel1.Height); //dsp.Top += span.Height;
                }
                if (e.Shift && !e.Control && !e.Alt)
                {
                    scrollSmooth(picMain.Left, picMain.Top + sp0.Panel1.Height / 2); //dsp.Top += span.Height / 2;
                }
                validateBounds();
                return;
            }

            // Sap bien tren-----------------------------------------------------------------------
            if (e.KeyCode == Keys.Up)
            {
                if (e.Control && !e.Shift && !e.Alt)
                {
                    scrollSmooth(picMain.Left, picMain.Top - sp0.Panel1.Height); //dsp.Top -= span.Height;
                }
                if (e.Shift && !e.Control && !e.Alt)
                {
                    scrollSmooth(picMain.Left, picMain.Top - sp0.Panel1.Height / 2); //dsp.Top -= span.Height / 2;
                }
                validateBounds();
                return;
            }

            // Sap bien phai-----------------------------------------------------------------------
            if (e.KeyCode == Keys.Right)
            {
                if (e.Control && !e.Shift && !e.Alt)
                {
                    scrollSmooth(picMain.Left + sp0.Panel1.Width, picMain.Top); //dsp.Left += span.Width;
                    validateBounds();
                }
                else if (e.Shift && !e.Control && !e.Alt)
                {
                    scrollSmooth(picMain.Left + sp0.Panel1.Width / 2, picMain.Top); //dsp.Left += span.Width / 2;
                    validateBounds();
                }
                return;

            }

            // Sap bien trai-----------------------------------------------------------------------
            if (e.KeyCode == Keys.Left)
            {
                if (e.Control && !e.Shift && !e.Alt)
                {
                    scrollSmooth(picMain.Left - sp0.Panel1.Width, picMain.Top); //dsp.Left -= span.Width;
                }
                if (e.Shift && !e.Control && !e.Alt)
                {
                    scrollSmooth(picMain.Left - sp0.Panel1.Width / 2, picMain.Top); //dsp.Left -= span.Width / 2;
                }
                validateBounds();
                return;
            }


            //if (e.KeyCode == Keys.B)
            //{
            //    picMain.BackgroundImage = null;
            //    if (e.Control) this.BackColor = Color.White;
            //    if (e.Shift) picMain.BackgroundImage = ImageGlass.Properties.Resources.caro;
            //    if (e.Alt) using (ColorDialog cd = new ColorDialog())
            //        {
            //            cd.ShowDialog();
            //            this.BackColor = cd.Color;
            //        }
            //    return;
            //}


            return;
        }

        #endregion 


        #region phuong thuc
        /// <summary>
        /// Set zoom pivot by reading viewport location
        /// </summary>
        void setZoomOrigin()
        {
            setZoomOrigin(getCursorPositionRelativeToWindowPositionThroughTheMathematicalImplementation());
        }


        /// <summary>
        /// Set zoom pivot based on mouseEvent
        /// </summary>
        /// <param name="pt">The clicked absolute coordinate of dsp</param>
        void setZoomOrigin(Point pt)
        {
            loc = getCursorPositionRelativeToWindowPosition();
            center = loc;
            offX = pt.X / (picMain.Width * 1.0);
            offY = pt.Y / (picMain.Height * 1.0);
            try
            {
                aspect = picMain.Image.Width / (1.0 * picMain.Image.Height);
            }
            catch { }
        }

        /// <summary>
        /// Check whether existing viewport is within allowed bounds
        /// Please don't use this method unless you want flickering
        /// </summary>
        /// <returns>The closest valid viewport based on reg</returns>
        Point validateBounds()
        {
            return validateBounds(picMain.Bounds, true);
        }

        /// <summary>
        /// Validate and (optionally) apply new viewport
        /// </summary>
        /// <param name="reg">The new viewport</param>
        /// <param name="exec">Apply viewport</param>
        /// <returns>The closest valid viewport based on reg</returns>
        Point validateBounds(Rectangle reg, bool exec)
        {
            int x = reg.Left, y = reg.Top;
            if (lockEdges)
            {

                // Validate width
                if (reg.Width >= sp0.Panel1.Width)
                {
                    // Larger than screen
                    if (x > 0) x = 0;
                    if (sp0.Panel1.Width > reg.Width + x)
                        x = -(reg.Width - sp0.Panel1.Width);
                }
                else
                {
                    // Smaller than screen
                    if (x < 0) x = 0;
                    if (sp0.Panel1.Width < reg.Width + x)
                        x = sp0.Panel1.Width - reg.Width;
                }

                // Validate height
                if (reg.Height >= sp0.Panel1.Height)
                {
                    // Larger than screen
                    if (y > 0) y = 0;
                    if (sp0.Panel1.Height > reg.Height + y)
                        y = -(reg.Height - sp0.Panel1.Height);
                }
                else
                {
                    // Smaller than screen
                    if (y < 0) y = 0;
                    if (sp0.Panel1.Height < reg.Height + y)
                        y = sp0.Panel1.Height - reg.Height;
                }
            }
            //bool ret = (x == reg.Left && y == reg.Top);
            if (exec) picMain.Location = new Point(x, y);
            return new Point(x, y);
        }

        // Relative position reference
        double offX, offY, aspect;
        Point loc = Point.Empty;
        Point center = Point.Empty;

        /// <summary>
        /// Handles mouseMove event (pan/zoom)
        /// </summary>
        /// <param name="sender">Event origin (control)</param>
        /// <param name="e">Event parameters</param>
        bool mouseMoveAvailable = true;
        private void picMain_MouseMove(object sender, MouseEventArgs e)
        {
            try
            {
                //change cursor
                if (int.Parse(picMain.Tag.ToString()) == 1)
                {
                    Bitmap img = ImageGlass.Properties.Resources.Hand_Down;
                    Cursor c = new Cursor(img.GetHicon());
                    picMain.Cursor = c;
                }
                else
                {
                    Bitmap img = ImageGlass.Properties.Resources.Hand_Move;
                    Cursor c = new Cursor(img.GetHicon());
                    picMain.Cursor = c;
                }


                if (!mouseMoveAvailable) return;
                mouseMoveAvailable = false;

                if (e.Button == MouseButtons.Right && !imgError)
                {

                    // ZOOOOOOOOM
                    Point pos = loc;
                    loc = getCursorPositionRelativeToWindowPosition();

                    // Just to make things less complicated
                    int diffX = loc.X - pos.X;
                    int diffY = loc.Y - pos.Y;

                    // Pythagoras to find length
                    double diff = Math.Sqrt(
                        Math.Pow(1.0 * diffX, 2) +
                        Math.Pow(1.0 * diffY, 2));

                    // Retain most weighted sign
                    if (Math.Abs(diffX) > Math.Abs(diffY))
                        diff *= Math.Sign(diffX);
                    else diff *= Math.Sign(diffY);

                    zoomImage(diff);

                }
                else if (e.Button == MouseButtons.Left)
                {

                    // Pan
                    Point pos = loc; loc = getCursorPositionRelativeToWindowPosition(); //Cursor.Position;

                    // Directly set location
                    //dsp.Left += Cursor.Position.X - pos.X;
                    //dsp.Top += Cursor.Position.Y - pos.Y;

                    // Validate not out of bounds
                    validateBounds(new Rectangle(
                        picMain.Left + (loc.X - pos.X),
                        picMain.Top + (loc.Y - pos.Y),
                        picMain.Width, picMain.Height), true);
                }
                mouseMoveAvailable = true;
            }
            catch { }
        }

        /// <summary>
        /// Feeling real ENTERPRISE
        /// </summary>
        /// <returns>The Cursor Position Relative To Window Position (Thus Not The Absolute Position Of The Cursor)</returns>
        Point getCursorPositionRelativeToWindowPosition()
        {
            Point ret = Cursor.Position;
            ret.X -= this.Left - chrome.X;
            ret.Y -= this.Top - chrome.Y;
            return ret;
        }

        /// <summary>
        /// Alternative vershun
        /// </summary>
        /// <returns>Mathematical variation of gCPRTWP; more suitable for zoomfix</returns>
        Point getCursorPositionRelativeToWindowPositionThroughTheMathematicalImplementation()
        {
            return new Point(
                Cursor.Position.X - picMain.Left - this.Left,
                Cursor.Position.Y - picMain.Top - this.Top);
        }

        /// <summary>
        /// Zooms the image lambda pizels
        /// </summary>
        /// <param name="lambda">Amount of pixels to append</param>
        void zoomImage(double lambda)
        {
            isZoom = true;

            // I'm too tired to figure out why this is
            // necessary right now, I'm just happy it works
            if (lambda < 0) lambda /= 1.6;

            // Slightly higher performance
            double w = picMain.Width; //, h = dsp.Height;

            // Calculate new size and offset
            double newW = Math.Max(25,
                w + w * 0.005 * lambda);
            double newH = newW / aspect;
            double newOffX = -(newW * offX) + center.X;
            double newOffY = -(newH * offY) + center.Y;

            // Apply the change
            if (newW * newH < 104857600)
            { //10240^2

                picMain.Width = (int)newW;
                picMain.Height = (int)newH;

                // Old pivot method; centered on screen
                //picMain.Left -= (int)(picMain.Width - w) / 2;
                //picMain.Top -= (int)(picMain.Height - h) / 2;

                // New pivot method; weighted on original rightclick coordinate
                if ((int)newOffY < 0)
                    picMain.Top = 0;
                else
                    picMain.Top = (int)newOffY;

                if ((int)newOffX < 0)
                    picMain.Left = 0;
                else
                    picMain.Left = (int)newOffX;

                Application.DoEvents();
            }
        }

        /// <summary>
        /// Smoothly scroll the image to given position
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        void scrollSmooth(int x, int y)
        {

            // Filter repetitious scrolls
            scrollIdent++;
            int myIdent = scrollIdent;

            // DERP
            if (!smoothPan) scrollInstant(x, y);

            // Make sure we're within bounds
            Point xy = validateBounds(new Rectangle(x, y, picMain.Width, picMain.Height), false);
            x = xy.X; y = xy.Y;         // expand validated position

            int xa = picMain.Left;          // read current ("from") pos
            int ya = picMain.Top;
            int xd = x - xa;            // difference between cur and target
            int yd = y - ya;
            int xs = Math.Sign(xd);     // get direction
            int ys = Math.Sign(yd);
            xd *= xs;                   // filter direction from distance
            yd *= ys;
            Size sz = picMain.Size;
            int[] stepsize = { 200, 100, 50, 25, 12, 6, 3, 2, 1 };
            while (xd > 1 || yd > 1)
            {
                bool xb = false, yb = false;            // stepped this axis yet?
                foreach (int step in stepsize)
                {        // try all stepsizes
                    Point newpos = new Point(xa, ya);   // original position
                    if (!xb && step < xd)
                    {             // can & should step X axis?
                        xd -= step;                     // subtract steps from dist
                        xa += step * (1 * xs);          // add step to position
                        xb = true;                      // stepped X axis
                    }
                    if (!yb && step < yd)
                    {
                        yd -= step;
                        ya += step * (1 * ys);
                        yb = true;
                    }
                    /*if (step < dist) {
                        dist -= step;
                        from += step * (-1 * sign);
                        if (!validateBounds(new Rectangle(dsp.Left, from, dsp.Width, dsp.Height))) dist = 0;
                        Application.DoEvents();
                        System.Threading.Thread.Sleep(50);
                        break;
                    }*/
                }
                if (myIdent != scrollIdent) break;
                validateBounds(new Rectangle(xa, ya, sz.Width, sz.Height), true);
                Application.DoEvents();
                System.Threading.Thread.Sleep(20);
            }
        }

        void scrollInstant(int x, int y)
        {
            validateBounds(new Rectangle(x, y, picMain.Width, picMain.Height), true);
        }

        /// <summary>
        /// Apply and center a best-fit viewport
        /// </summary>
        void Recenter()
        {
            if (picMain.Image != null) Recenter(picMain.Image);
        }

        /// <summary>
        /// Apply and center a best-fit viewport based on supplied bitmap
        /// </summary>
        /// <param name="bm">Image to base calculations on</param>
        void Recenter(Image bm)
        {            
            int durrX, durrY;
            double derpX = bm.Width / (1.0 * sp0.Panel1.Width);
            double derpY = bm.Height / (1.0 * sp0.Panel1.Height);

            if (derpX > derpY)
            {
                durrX = sp0.Panel1.Width;
                durrY = (int)(bm.Height / derpX);
                picMain.Location = new Point(0, (sp0.Panel1.Height - durrY) / 2);
            }
            else
            {
                durrY = sp0.Panel1.Height;
                durrX = (int)(bm.Width / derpY);
                picMain.Location = new Point((sp0.Panel1.Width - durrX) / 2, 0);
            }

            picMain.Size = new Size(durrX, durrY);
                        
        }

        Rectangle StringToRect(string str)
        {
            string[] args = str.Split(',');
            int[] arg = new int[args.Length];
            for (int a = 0; a < arg.Length; a++)
            {
                arg[a] = Convert.ToInt32(args[a]);
            }
            return new Rectangle(arg[0], arg[1], arg[2], arg[3]);
        }

        string RectToString(Rectangle rc)
        {
            return rc.Left + "," + rc.Top + "," + rc.Width + "," + rc.Height;
        }
        #endregion


        #region Configuration
        /// <summary>
        /// Áp dụng theme mặc định
        /// </summary>
        private void LoadThemeDefault()
        {
            // <main>
            toolMain.BackgroundImage = ImageGlass.Properties.Resources.topbar;
            sp0.Panel2.BackgroundImage = ImageGlass.Properties.Resources.bottombar;
            lblStatus.ForeColor = Color.Black;
            this.BackColor = Color.White;
            string hkey = "HKEY_CURRENT_USER\\SOFTWARE\\PhapSoftware\\ImageGlass\\";
            Registry.SetValue(hkey, "BackColor", this.BackColor.ToArgb().ToString());

            // <toolbar_icon>
            btnBack.Image = ImageGlass.Properties.Resources.back;
            btnNext.Image = ImageGlass.Properties.Resources.next;
            btnRotateLeft.Image = ImageGlass.Properties.Resources.leftrotate;
            btnRotateRight.Image = ImageGlass.Properties.Resources.rightrotate;
            btnZoomIn.Image = ImageGlass.Properties.Resources.zoomin;
            btnZoomOut.Image = ImageGlass.Properties.Resources.zoomout;
            btnScale11.Image = ImageGlass.Properties.Resources.scaletofit;
            btnScaletoWidth.Image = ImageGlass.Properties.Resources.scaletowidth;
            btnScaletoHeight.Image = ImageGlass.Properties.Resources.scaletoheight;
            btnWindowAutosize.Image = ImageGlass.Properties.Resources.autosizewindow;
            btnOpen.Image = ImageGlass.Properties.Resources.open;
            btnRefresh.Image = ImageGlass.Properties.Resources.refresh;
            btnGoto.Image = ImageGlass.Properties.Resources.gotoimage;
            btnThumb.Image = ImageGlass.Properties.Resources.thumbnail;
            btnCaro.Image = ImageGlass.Properties.Resources.caro1;
            btnFullScreen.Image = ImageGlass.Properties.Resources.fullscreen;
            btnSlideShow.Image = ImageGlass.Properties.Resources.slideshow;
            btnConvert.Image = ImageGlass.Properties.Resources.convert;
            btnSetting.Image = ImageGlass.Properties.Resources.settings;
            btnHelp.Image = ImageGlass.Properties.Resources.about;
            btnLike.Image = ImageGlass.Properties.Resources.like;
            btnDisLike.Image = ImageGlass.Properties.Resources.dislike;
            btnReport.Image = ImageGlass.Properties.Resources.report;

            Registry.SetValue(hkey, "Theme", "default");
        }

        /// <summary>
        /// Thay đổi theme
        /// </summary>
        private void LoadTheme()
        {
            string hkey = "HKEY_CURRENT_USER\\SOFTWARE\\PhapSoftware\\ImageGlass\\";
            string themeFile = Registry.GetValue(hkey, "Theme", "default").ToString();

            if (File.Exists(themeFile))
            {
                Theme.Theme t = new Theme.Theme(themeFile);
                string dir = (Path.GetDirectoryName(themeFile) + "\\").Replace("\\\\", "\\");
                
                // <main>
                try { toolMain.BackgroundImage = Image.FromFile(dir + t.topbar); }
                catch { toolMain.BackgroundImage = null; }

                try { sp0.Panel2.BackgroundImage = Image.FromFile(dir + t.bottombar); }
                catch { sp0.Panel2.BackgroundImage = null; }

                try { lblStatus.ForeColor = t.statuscolor; }
                catch { lblStatus.ForeColor = Color.Black; }

                try { this.BackColor = t.backcolor; }
                catch { this.BackColor = Color.White; }
                Registry.SetValue(hkey, "BackColor", this.BackColor.ToArgb().ToString());

                // <toolbar_icon>
                try { btnBack.Image = Image.FromFile(dir + t.back); }
                catch { btnBack.Image = ImageGlass.Properties.Resources.noimg; }

                try { btnNext.Image = Image.FromFile(dir + t.next); }
                catch { btnNext.Image = ImageGlass.Properties.Resources.noimg; }

                try { btnRotateLeft.Image = Image.FromFile(dir + t.leftrotate); }
                catch { btnRotateLeft.Image = ImageGlass.Properties.Resources.noimg; }

                try { btnRotateRight.Image = Image.FromFile(dir + t.rightrotate); }
                catch { btnRotateRight.Image = ImageGlass.Properties.Resources.noimg; }

                try { btnZoomIn.Image = Image.FromFile(dir + t.zoomin); }
                catch { btnZoomIn.Image = ImageGlass.Properties.Resources.noimg; }

                try { btnZoomOut.Image = Image.FromFile(dir + t.zoomout); }
                catch { btnZoomOut.Image = ImageGlass.Properties.Resources.noimg; }

                try { btnScale11.Image = Image.FromFile(dir + t.scaletofit); }
                catch { btnScale11.Image = ImageGlass.Properties.Resources.noimg; }

                try { btnScaletoWidth.Image = Image.FromFile(dir + t.scaletowidth); }
                catch { btnScaletoWidth.Image = ImageGlass.Properties.Resources.noimg; }

                try { btnScaletoHeight.Image = Image.FromFile(dir + t.scaletoheight); }
                catch { btnScaletoHeight.Image = ImageGlass.Properties.Resources.noimg; }

                try { btnWindowAutosize.Image = Image.FromFile(dir + t.autosizewindow); }
                catch { btnWindowAutosize.Image = ImageGlass.Properties.Resources.noimg; }

                try { btnOpen.Image = Image.FromFile(dir + t.open); }
                catch { btnOpen.Image = ImageGlass.Properties.Resources.noimg; }

                try { btnRefresh.Image = Image.FromFile(dir + t.refresh); }
                catch { btnRefresh.Image = ImageGlass.Properties.Resources.noimg; }

                try { btnGoto.Image = Image.FromFile(dir + t.gotoimage); }
                catch { btnGoto.Image = ImageGlass.Properties.Resources.noimg; }

                try { btnThumb.Image = Image.FromFile(dir + t.thumbnail); }
                catch { btnThumb.Image = ImageGlass.Properties.Resources.noimg; }

                try { btnCaro.Image = Image.FromFile(dir + t.caro); }
                catch { btnCaro.Image = ImageGlass.Properties.Resources.noimg; }

                try { btnFullScreen.Image = Image.FromFile(dir + t.fullscreen); }
                catch { btnFullScreen.Image = ImageGlass.Properties.Resources.noimg; }

                try { btnSlideShow.Image = Image.FromFile(dir + t.slideshow); }
                catch { btnSlideShow.Image = ImageGlass.Properties.Resources.noimg; }

                try { btnConvert.Image = Image.FromFile(dir + t.convert); }
                catch { btnConvert.Image = ImageGlass.Properties.Resources.noimg; }

                try { btnSetting.Image = Image.FromFile(dir + t.settings); }
                catch { btnSetting.Image = ImageGlass.Properties.Resources.noimg; }

                try { btnHelp.Image = Image.FromFile(dir + t.about); }
                catch { btnHelp.Image = ImageGlass.Properties.Resources.noimg; }

                try { btnLike.Image = Image.FromFile(dir + t.like); }
                catch { btnLike.Image = ImageGlass.Properties.Resources.noimg; }

                try { btnDisLike.Image = Image.FromFile(dir + t.dislike); }
                catch { btnDisLike.Image = ImageGlass.Properties.Resources.noimg; }

                try { btnReport.Image = Image.FromFile(dir + t.report); }
                catch { btnReport.Image = ImageGlass.Properties.Resources.noimg; }

                Registry.SetValue(hkey, "Theme", themeFile);
            }
            else
            {
                LoadThemeDefault();
            }

        }

        /// <summary>
        /// Tải dữ liệu từ Registry
        /// </summary>
        void LoadConfig()
        {
            string hkey = "HKEY_CURRENT_USER\\SOFTWARE\\PhapSoftware\\ImageGlass\\";
            Registry.SetValue(hkey, "igVersion", Application.ProductVersion);

            //Windows Bound (Position + Size)------------------------------------------------
            Rectangle rc = StringToRect(Registry.GetValue(hkey, "WindowsBound",
                                        "280,125,750,545").ToString());
            this.Bounds = rc;
            
            //windows state--------------------------------------------------------------
            string s = Registry.GetValue(hkey, "WindowsState", "Normal").ToString();
            if (s == "Normal")
            {
                this.WindowState = FormWindowState.Normal;
            }
            else if (s == "Maximized")
            {
                this.WindowState = FormWindowState.Maximized;
            }

            //Slideshow Interval----------------------------------------------------------
            int i = int.Parse(Registry.GetValue(hkey, "Interval", "5").ToString());
            if (!(0 < i && i < 61)) i = 5;//gioi han thoi gian [1; 60] giay
            timSlideShow.Interval = 1000 * i;

            //Show Caro
            if (bool.Parse(Registry.GetValue(hkey, "Caro", "False").ToString()))
            {
                btnCaro.PerformClick();
            }

            //Khoá khung ảnh---------------------------------------------------------------
            lockEdges = bool.Parse(Registry.GetValue(hkey, "LockToEdge", "True").ToString());
           
            //Tìm ảnh đệ quy----------------------------------------------------------------
            recursive = bool.Parse(Registry.GetValue(hkey, "Recursive", "False").ToString());
            
            //Lăn chuột mượt----------------------------------------------------------------
            smoothPan = bool.Parse(Registry.GetValue(hkey, "SmoothPanning", "False").ToString());
            
            //Load theme--------------------------------------------------------------------
            LoadTheme();
            
            
        }

        /// <summary>
        /// Lưu dữ liệu xuống Registry
        /// </summary>
        void SaveConfig()
        {
            string hkey = "HKEY_CURRENT_USER\\SOFTWARE\\PhapSoftware\\ImageGlass\\";

            if (this.WindowState == FormWindowState.Normal)
            {
                //Windows Bound-------------------------------------------------------------------
                Registry.SetValue(hkey, "WindowsBound", RectToString(rect == Rectangle.Empty ?
                                                                    this.Bounds : rect));
            }            

            //Windows State-------------------------------------------------------------------
            Registry.SetValue(hkey, "WindowsState", this.WindowState);
            
            //Caro Style
            Registry.SetValue(hkey, "Caro", btnCaro.Checked.ToString());
            
            //Lan chuot muot------------------------------------------------------------------
            Registry.SetValue(hkey, "SmoothPanning", smoothPan);
            
        }

        #endregion


        #region Form event
        private void frmMain_Load(object sender, EventArgs e)
        {
            Application.DoEvents();
            LoadConfig();

            //gan danh sach cac ext ho tro
            string[] ext = {"bmp", "dib", "jpg", "jpe", "jfif", "jpeg", 
                             "png", "gif", "ico", "tif", "tiff", "emf",
                             "exif", "wmf", "tga"};
            dsExt.AddRange(ext);

            if (Program.args.Length > 0)
            {
                if (File.Exists(Program.args[0]))
                {
                    FileInfo f = new FileInfo(Program.args[0]);
                    Prepare(f.FullName);
                }
                else if (Directory.Exists(Program.args[0]))
                {
                    DirectoryInfo d = new DirectoryInfo(Program.args[0]);
                    Prepare(d.FullName);
                }
            }

            // Apply zooming with scroll wheel
            this.MouseWheel += new MouseEventHandler(picMain_MouseWheel);

            System.GC.Collect();
        }

        /// <summary>
        /// Removes empty folders on exit
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            SaveConfig();
        }

        /// <summary>
        /// I wonder what this does
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void picMain_MouseDown(object sender, MouseEventArgs e)
        {

            // Set chrome (non-userspace) padding
            chrome = new Point(
                (e.X + picMain.Left) - (Cursor.Position.X - this.Left),
                (e.Y + picMain.Top) - (Cursor.Position.Y - this.Top));

            setZoomOrigin(e.Location);
            picMain.Tag = 1;

            Bitmap img = ImageGlass.Properties.Resources.Hand_Down;
            Cursor c = new Cursor(img.GetHicon());
            picMain.Cursor = c;

        }

        /// <summary>
        /// Hurr
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmMain_Resize(object sender, EventArgs e)
        {
            try
            {

                if (man.Get(cur).Width <= sp0.Panel1.Width && man.Get(cur).Height <= sp0.Panel1.Height)
                {
                    Point p = new Point();
                    p.X = sp0.Panel1.Width / 2 - man.Get(cur).Width / 2;
                    p.Y = sp0.Panel1.Height / 2 - man.Get(cur).Height / 2;

                    picMain.Image = man.Get(cur);
                    picMain.Bounds = new Rectangle(p, picMain.Image.Size);
                }
                else
                {
                    Recenter(); //NO DOCKING ALLOWED
                }
            }
            catch { }

        }

        /// <summary>
        /// Zoom
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void picMain_MouseWheel(object sender, MouseEventArgs e)
        {
            if (imgError)
            {
                return;
            }
            setZoomOrigin();
            zoomImage(e.Delta);
        }

        private void btnNext_Click(object sender, EventArgs e)
        {
            NextPic(1);//xem anh ke tiep
        }

        private void btnBack_Click(object sender, EventArgs e)
        {
            NextPic(-1);//xem anh truoc do
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            try
            {
                if (!File.Exists(man.GetPath(cur)))
                {
                    return;
                }
            }
            catch { return; }
            Prepare(man.GetPath(cur));//cap nhat lai thu muc anh
        }

        private void btnRotateRight_Click(object sender, EventArgs e)
        {
            if (man.Length < 1 || imgError)
            {
                return;
            }

            man.filter.IncRotate(1);
            NextPic(0);
        }

        private void btnRotateLeft_Click(object sender, EventArgs e)
        {
            if (man.Length < 1 || imgError)
            {
                return;
            }

            man.filter.IncRotate(-1);
            NextPic(0);
        }


        private void btnOpen_Click(object sender, EventArgs e)
        {
            OpenFile();
        }


        private void btnThumb_Click(object sender, EventArgs e)
        {
            isShowThumbnail = !isShowThumbnail;
            sp0.Panel2Collapsed = !isShowThumbnail;
            toolThumbBar.Visible = isShowThumbnail;

            if (isShowThumbnail)
            {
                sp0.Panel2MinSize = 119;
                if (toolThumbBar.Items.Count == 0)
                {
                    LoadThumnailImage(dsImage.ToArray());
                }
            }
        }

        private void btnScale11_Click(object sender, EventArgs e)
        {
            if (man.Length < 1 || imgError)
            {
                return;
            }

            Point l = new Point();
            isZoom = false;

            l.X = sp0.Panel1.Width / 2 - picMain.Width / 2;
            l.Y = sp0.Panel1.Height / 2 - picMain.Width / 2;

            picMain.Bounds = new Rectangle(l, picMain.Image.Size);

        }

        private void btnScaletoWidth_Click(object sender, EventArgs e)
        {
            if (man.Length < 1 || imgError)
            {
                return;
            }
            // Scale to Width
            double frac = sp0.Panel1.Width / (1.0 * picMain.Image.Width);
            int height = (int)(picMain.Image.Height * frac);
            picMain.Bounds = new Rectangle(Point.Empty, new Size(sp0.Panel1.Width, height));
        }

        private void btnScaletoHeight_Click(object sender, EventArgs e)
        {
            if (man.Length < 1 || imgError)
            {
                return;
            }
            // Scale to Height
            double frac = sp0.Panel1.Height / (1.0 * picMain.Image.Height);
            int width = (int)(picMain.Image.Width * frac);
            picMain.Bounds = new Rectangle(Point.Empty, new Size(width, sp0.Panel1.Height));
        }

        private void btnWindowAutosize_Click(object sender, EventArgs e)
        {
            if (man.Length < 1 || imgError)
            {
                return;
            }
            // In Soviet Russia, window adapt to image
            Rectangle screen = Screen.FromControl(this).WorkingArea;
            this.WindowState = FormWindowState.Normal;
            this.Size = new Size(Width += picMain.Image.Width - sp0.Panel1.Width,
                                Height += picMain.Image.Height - sp0.Panel1.Height);
            //Application.DoEvents();
            picMain.Bounds = new Rectangle(Point.Empty, picMain.Image.Size);
            this.Top = (screen.Height - this.Height) / 2 + screen.Top;
            this.Left = (screen.Width - this.Width) / 2 + screen.Left;
        }

        private void btnGoto_Click(object sender, EventArgs e)
        {
            int n = cur;
            string s = InputBox.Derp("Enter the image index to view it. Press [ENTER] ", "0");

            if (int.TryParse(s, out n))
            {
                n--;

                if (-1 < n && n < man.Length)
                {
                    cur = n;
                    NextPic(0);
                }
            }
        }

        private void btnCaro_Click(object sender, EventArgs e)
        {
            if (btnCaro.Checked)
            {
                picMain.BackgroundImage = ImageGlass.Properties.Resources.caro;
            }
            else
            {
                picMain.BackgroundImage = null;
            }
        }

        private void btnZoomIn_Click(object sender, EventArgs e)
        {
            if (!imgError)
            {
                setZoomOrigin();
                zoomImage(14);
            }
        }

        private void btnZoomOut_Click(object sender, EventArgs e)
        {
            if (!imgError)
            {
                setZoomOrigin();
                zoomImage(-14);
            }
        }

        private void timSlideShow_Tick(object sender, EventArgs e)
        {
            NextPic(1);
        }

        private void btnSlideShow_Click(object sender, EventArgs e)
        {
            if (man.Length < 1)
            {
                return;
            }

            //full screen
            if (this.rect == Rectangle.Empty)
            {
                this.rect = this.Bounds;
                this.FormBorderStyle = FormBorderStyle.None;
                this.WindowState = FormWindowState.Normal;
                this.BackColor = Color.Black;
                toolMain.Visible = false;
                Application.DoEvents();
                this.Bounds = Screen.FromControl(this).Bounds;

                timSlideShow.Start();
                timSlideShow.Enabled = true;

                slideshow = true;
                mnuStartSlideshow.Visible = true;
                mnuStopSlideshow.Visible = true;
                mnuExitSlideshow.Visible = true;
                mnuPhanCach.Visible = true;
                mnuStartSlideshow.Enabled = false;
                mnuStopSlideshow.Enabled = true;
            }
        }

        private void btnFullScreen_Click(object sender, EventArgs e)
        {
            //full screen
            if (this.rect == Rectangle.Empty)
            {
                this.rect = this.Bounds;
                this.FormBorderStyle = FormBorderStyle.None;
                this.WindowState = FormWindowState.Normal;
                Application.DoEvents();
                this.Bounds = Screen.FromControl(this).Bounds;
            }
            //exit full screen
            else
            {
                this.FormBorderStyle = FormBorderStyle.Sizable;
                this.WindowState = FormWindowState.Normal;
                Application.DoEvents();
                this.Bounds = this.rect;
                this.rect = Rectangle.Empty;
            }
        }


        private void picMain_MouseUp(object sender, MouseEventArgs e)
        {
            picMain.Tag = 0;
            Bitmap img = ImageGlass.Properties.Resources.Hand_Move;
            Cursor c = new Cursor(img.GetHicon());
            picMain.Cursor = c;
        }

        private void btnSetting_Click(object sender, EventArgs e)
        {
            frmSetting f = new frmSetting();
            f.Show();
        }


        void mnuEditWithPaint_Click(object sender, EventArgs e)
        {
            if (!imgError)
            {
                System.Diagnostics.Process.Start("mspaint.exe", char.ConvertFromUtf32(34) + man.GetPath(cur) + char.ConvertFromUtf32(34));
            }
        }

        void mnuProperties_Click(object sender, EventArgs e)
        {
            ImageGlass_ImageInfo.DisplayFileProperties(man.GetPath(cur), this.Handle);
        }

        void mnuImageLocation_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start("explorer.exe", "/select,\"" + man.GetPath(cur) + "\"");
        }

        void mnuDelete_Click(object sender, EventArgs e)
        {
            try
            {
                if (!File.Exists(man.GetPath(cur)))
                {
                    return;
                }
            }
            catch { return; }

            DialogResult msg = MessageBox.Show("Delete file '" + man.GetPath(cur) + "' ?",
                "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (msg == DialogResult.Yes)
            {
                string f = man.GetPath(cur);

                System.GC.Collect();
                man.Remove(cur);
                picMain.Image = null;

                toolThumbBar.RemoveItems(cur);
                toolThumbBar.LoadThumbnailItems();

                try
                {
                    ImageGlass_Image.DeleteFile(f, false);
                    NextPic(0);
                }
                catch { }
            }
        }

        void mnuRecycleBin_Click(object sender, EventArgs e)
        {
            try
            {
                if (!File.Exists(man.GetPath(cur)))
                {
                    return;
                }
            }
            catch { return; }

            DialogResult msg = MessageBox.Show("Send file '" + man.GetPath(cur) + "' to recycle bin?",
                "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (msg == DialogResult.Yes)
            {
                string f = man.GetPath(cur);

                System.GC.Collect();
                man.Remove(cur);
                picMain.Image = null;

                toolThumbBar.RemoveItems(cur);
                toolThumbBar.LoadThumbnailItems();

                try
                {
                    ImageGlass_Image.DeleteFile(f, true);
                    NextPic(0);
                }
                catch { }
            }
        }

        void mnuWallpaper_Click(object sender, EventArgs e)
        {
            if (!imgError)
            {
                ImageGlass_Image.SetWallpaper(man.GetPath(cur));
            }
        }

        void mnuExtractFrames_Click(object sender, EventArgs e)
        {
            if (!imgError)
            {
                FolderBrowserDialog f = new FolderBrowserDialog();
                f.Description = "Select output folder";
                f.ShowNewFolderButton = true;
                DialogResult res = f.ShowDialog();

                if (res == DialogResult.OK && Directory.Exists(f.SelectedPath))
                {
                    ImageGlass_Animation.ExtractAllFrames(man.GetPath(cur), f.SelectedPath);
                }

                f = null;
            }
        }

        private void btnHelp_Click(object sender, EventArgs e)
        {
            frmAbout f = new frmAbout();
            f.ShowDialog();
        }

        private void btnConvert_Click(object sender, EventArgs e)
        {
            try
            {
                if (!File.Exists(man.GetPath(cur)) || imgError)
                {
                    return;
                }
            }
            catch { return; }
            ImageGlass_Image.ConvertImage(picMain.Image, man.GetName(cur));
        }

        private void timGC_Tick(object sender, EventArgs e)
        {
            System.GC.Collect();
        }

        private void btnLike_Click(object sender, EventArgs e)
        {
            try
            {
                System.Diagnostics.Process.Start(char.ConvertFromUtf32(34) +
                                (Application.StartupPath + "\\").Replace("\\\\", "\\") + "igcmd.exe" +
                                char.ConvertFromUtf32(34), "iglike " + Application.ProductVersion);
            }
            catch { }
        }

        private void btnDisLike_Click(object sender, EventArgs e)
        {
            try
            {
                System.Diagnostics.Process.Start(char.ConvertFromUtf32(34) +
                                (Application.StartupPath + "\\").Replace("\\\\", "\\") + "igcmd.exe" +
                                char.ConvertFromUtf32(34), "igdislike " + Application.ProductVersion);
            }
            catch { }
        }

        private void btnReport_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start("http://code.google.com/p/imageglass/issues/");
        }

        private void picMain_Paint(object sender, PaintEventArgs e)
        {
            if (man.Length < 1 || isZoom == false) return;

            Graphics g = e.Graphics;

            string hkey = "HKEY_CURRENT_USER\\Software\\PhapSoftware\\ImageGlass\\";
            string z = Microsoft.Win32.Registry.GetValue(hkey, "ZoomOptimize", "auto").ToString();
            if (z.ToLower() == "smooth pixels")
            {
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
            }
            else if (z.ToLower() == "clear pixels")
            {
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
            }
            else //auto
            {
                if (man.Get(cur).Width * man.Get(cur).Height > picMain.Width * picMain.Height)
                    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
                else
                    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
            }

            g.DrawImage(man.Get(cur), 0, 0, picMain.Width, picMain.Height);
        }

        private void frmMain_ResizeEnd(object sender, EventArgs e)
        {
            SaveConfig();
        }

        private void mnuPopup_Opening(object sender, CancelEventArgs e)
        {
            try
            {
                if (!File.Exists(man.GetPath(cur)) || imgError)
                {
                    e.Cancel = true;
                    return;
                }
            }
            catch { e.Cancel = true; return; }

            try
            {
                int i = man.Get(cur).GetFrameCount(System.Drawing.Imaging.FrameDimension.Time);
                mnuExtractFrames.Text = "&Extract image frames (" + i.ToString() + ")";
                mnuExtractFrames.Enabled = true;
            }
            catch
            {
                mnuExtractFrames.Enabled = false;
            }
        }

        private void mnuPopup_Closing(object sender, ToolStripDropDownClosingEventArgs e)
        {
            mnuExtractFrames.Enabled = false;
        }

        private void mnuExitSlideshow_Click(object sender, EventArgs e)
        {
            timSlideShow.Stop();
            timSlideShow.Enabled = false;

            this.BackColor = Color.White;
            toolMain.Visible = true;

            this.FormBorderStyle = FormBorderStyle.Sizable;
            this.WindowState = FormWindowState.Normal;

            Application.DoEvents();
            this.Bounds = this.rect;
            this.rect = Rectangle.Empty;

            mnuStartSlideshow.Visible = false;
            mnuStopSlideshow.Visible = false;
            mnuExitSlideshow.Visible = false;
            mnuPhanCach.Visible = false;
        }

        private void mnuStartSlideshow_Click(object sender, EventArgs e)
        {
            timSlideShow.Enabled = true;
            timSlideShow.Start();
            mnuStartSlideshow.Enabled = false;
            mnuStopSlideshow.Enabled = true;
        }

        private void mnuStopSlideshow_Click(object sender, EventArgs e)
        {
            timSlideShow.Enabled = false;
            timSlideShow.Stop();
            mnuStartSlideshow.Enabled = true;
            mnuStopSlideshow.Enabled = false;
        }
        
        
        private void sp0_Panel1_MouseEnter(object sender, EventArgs e)
        {
            picMain.Focus();
        }

        private void toolThumbBar_MouseEnter(object sender, EventArgs e)
        {
            //toolThumbBar.Focus();
        }

        private void picMain_MouseEnter(object sender, EventArgs e)
        {
            picMain.Focus();
        }


        #endregion

      

        


        

        

      
        

    
    }
}